[AWS Glue]データカタログに作成されたパーティションをAWS CLIで削除してみた
こんにちは、CX事業本部の若槻です。
AWS Glueでは、パーティション分割を行うことによりデータの整理や効率的なクエリ実行を行うことが可能です。
このパーティションですが、開発時の検証のために作成済みのものを削除したい時があります。
そこで今回は、AWS Glueのデータカタログに作成されたパーティションをAWS CLIで削除する方法を確認してみました。
やってみた
ここでは、「AWS CLIのglue
コマンド」と「Athenaでのクエリ実行」の2通りの方法について確認してみます。
最初に以降のコマンド実行で使用する変数を定義しておきます。
% AWS_REGION=ap-northeast-1 % ACCOUNT_ID=$(aws sts get-caller-identity | jq -r ".Account") % RAW_DATA_BUCKET=s3://devices-raw-data-${ACCOUNT_ID}-${AWS_REGION} % GLUE_DATABASE_NAME=devices_data_analystics % GLUE_TABLE_NAME=devices_raw_data % ATHENA_WORK_GROUP_NAME=devices-data-analytics
環境構築
CloudFormationスタック
CloudFormationスタックのテンプレートです。
AWSTemplateFormatVersion: '2010-09-09' Resources: DevicesRawDataBucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub devices-raw-data-${AWS::AccountId}-${AWS::Region} DevicesDataAnalyticsAthenaWorkGroup: Type: AWS::Athena::WorkGroup Properties: Name: devices-data-analytics WorkGroupConfiguration: ResultConfiguration: OutputLocation: !Sub s3://${DevicesRawDataBucket}/query-result EnforceWorkGroupConfiguration: true PublishCloudWatchMetricsEnabled: true DevicesDataAnalyticsGlueDatabase: Type: AWS::Glue::Database Properties: CatalogId: !Ref AWS::AccountId DatabaseInput: Name: devices_data_analystics DevicesRawDataGlueTable: Type: AWS::Glue::Table Properties: CatalogId: !Ref AWS::AccountId DatabaseName: !Ref DevicesDataAnalyticsGlueDatabase TableInput: Name: devices_raw_data TableType: EXTERNAL_TABLE Parameters: has_encrypted_data: false serialization.encoding: utf-8 EXTERNAL: true StorageDescriptor: OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat Columns: - Name: device_id Type: string - Name: timestamp Type: bigint - Name: state Type: boolean InputFormat: org.apache.hadoop.mapred.TextInputFormat Location: !Sub s3://${DevicesRawDataBucket}/raw-data SerdeInfo: Parameters: paths: "device_id, timestamp, state" SerializationLibrary: org.apache.hive.hcatalog.data.JsonSerDe PartitionKeys: - Name: year Type: string - Name: month Type: string - Name: day Type: string
リソース定義DevicesRawDataGlueTable
で、year
、month
、day
の3つのパーティションキーを持ったGlueテーブルを作成しています。
スタックをデプロイします。
% aws cloudformation deploy \ --template-file template.yaml \ --stack-name devices-data-analytics-stack \ --capabilities CAPABILITY_NAMED_IAM \ --no-fail-on-empty-changeset
データの準備
データソースの場所となるS3バケットのパスに3種類のパーティションパスのオブジェクトを作成します。
{"device_id": "3ff9c44a", "timestamp": 1609348014, "state": true}
% aws s3 cp raw-data.json \ ${RAW_DATA_BUCKET}/raw-data/year=2021/month=01/day=13/raw-data.json % aws s3 cp raw-data.json \ ${RAW_DATA_BUCKET}/raw-data/year=2021/month=01/day=14/raw-data.json % aws s3 cp raw-data.json \ ${RAW_DATA_BUCKET}/raw-data/year=2021/month=01/day=15/raw-data.json
共通スクリプトの用意
パーティション一括作成および一括取得の簡易化のため、共通スクリプトをMakefileで用意しておきます。
export AWS_REGION=ap-northeast-1 export ACCOUNT_ID=$(shell aws sts get-caller-identity | jq -r ".Account") export GLUE_DATABASE_NAME=devices_data_analystics export GLUE_TABLE_NAME=devices_raw_data export ATHENA_WORK_GROUP_NAME=devices-data-analytics #パーティション一括作成 create-partitions: aws athena start-query-execution \ --query-string "MSCK REPAIR TABLE $(GLUE_TABLE_NAME)" \ --work-group $(ATHENA_WORK_GROUP_NAME) \ --query-execution-context Database=$(GLUE_DATABASE_NAME),Catalog=AwsDataCatalog #パーティション一括取得 get-partitions: partitions=$$(aws glue get-partitions \ --database-name $(GLUE_DATABASE_NAME) \ --table-name $(GLUE_TABLE_NAME) \ --query Partitions\ );\ len=$$(echo $$partitions | jq length);\ for i in $$(seq 0 $$(($$len - 1)) );\ do echo $$partitions | jq ".[$$i].Values";\ done
AWS CLIのglue
コマンドによる方法
一つのパーティションの削除
パーティションを一つ削除する場合はdelete-partition
コマンドで可能です。
パーティションを一括作成した上で、year=2021,month=01,day=13
のパーティションを削除してみます。
% make create-partitions % aws glue delete-partition \ --database-name ${GLUE_DATABASE_NAME} \ --table-name ${GLUE_TABLE_NAME} \ --partition-values 2021 01 13
パーティションを一括取得してみると、day=13
のパーティションだけ削除されて、day=14
およびday=15
のパーティションが残っていますね。
% make get-partitions [ "2021", "01", "14" ] [ "2021", "01", "15" ]
複数のパーティションの削除
複数のパーティションの一括削除はbatch-delete-partition
コマンドで可能です。
パーティションを一括作成し、batch-delete-partition
でday=13
およびday=14
を指定して実行してみます。({"Errors": [], ...}
のような実行結果が表示されますが無視してください)
% make create-partitions % aws glue batch-delete-partition \ --database-name ${GLUE_DATABASE_NAME} \ --table-name ${GLUE_TABLE_NAME} \ --partitions-to-delete Values=2021,01,13 Values=2021,01,14
パーティションを一括取得してみると、day=13
およびday=14
のパーティションが削除されて、day=15
のパーティションだけ残っていますね。
% make get-partitions [ "2021", "01", "15" ]
Athenaでのクエリ実行による方法
Athenaでのクエリ実行でパーティションを削除したい場合は、ALTER TABLE DROP PARTITION
クエリを使えば一つまたは複数の削除のいずれにも対応可能です。
一つのパーティションの削除
パーティションを一括作成して、ALTER TABLE DROP PARTITION
クエリでyear=2021,month=01,day=13
を指定して削除してみます。
% make create-partitions % queryString="ALTER TABLE ${GLUE_TABLE_NAME} DROP PARTITION (year='2021', month='01', day='13')" % aws athena start-query-execution \ --query-string ${queryString} \ --work-group ${ATHENA_WORK_GROUP_NAME} \ --query-execution-context Database=${GLUE_DATABASE_NAME},Catalog=AwsDataCatalog
パーティションを一括取得してみると、day=13
のパーティションだけ削除されて、day=14
およびday=15
のパーティションが残っていますね。
% make get-partitions [ "2021", "01", "14" ] [ "2021", "01", "15" ]
複数のパーティションの削除
パーティションを一括作成して、ALTER TABLE DROP PARTITION
クエリでday=13
およびday=14
のパーティションを指定して削除してみます。
% make create-partitions % queryString="ALTER TABLE ${GLUE_TABLE_NAME} DROP PARTITION (year='2021', month='01', day='13'), PARTITION (year='2021', month='01', day='14')" % aws athena start-query-execution \ --query-string ${queryString} \ --work-group ${ATHENA_WORK_GROUP_NAME} \ --query-execution-context Database=${GLUE_DATABASE_NAME},Catalog=AwsDataCatalog
パーティションを一括取得してみると、day=13
およびday=14
のパーティションが削除されて、day=15
のパーティションだけ残っていますね。
% make get-partitions [ "2021", "01", "15" ]
すべてのパーティションを一括削除できないの?
できなさそうです。ただし近い方法としてAthenaによるALTER TABLE DROP PARTITION
クエリ実行であれば、一番カーディナリティが低いパーティションキーをすべて指定して削除する方法が良さそうでした。これなら今回のデータであれば(year='2021')
を指定するだけで一括削除できます。
% make create-partitions % queryString="ALTER TABLE ${GLUE_TABLE_NAME} DROP PARTITION (year='2021')" % aws athena start-query-execution \ --query-string ${queryString} \ --work-group ${ATHENA_WORK_GROUP_NAME} \ --query-execution-context Database=${GLUE_DATABASE_NAME},Catalog=AwsDataCatalog
また、出来そうで出来なかったクエリへの指定として、(year<>'')
や(year is not null)
、(year>'0')
、(year!='')
などがありました(実行してもエラーとなる)。下記によるとHive標準では使えるようですがAthenaでは使えないようです。
glue
コマンドの場合は、get-partitions
での取得結果をShellでゴニョゴニョしてbatch-delete-partition
に渡すしか無さそうです。下記が参考になります。
場合によってはGlueテーブルを作り直した方が手っ取り早いかも知れませんね。
おわりに
AWS Glueのデータカタログに作成されたパーティションをAWS CLIで削除する方法を確認してみました。
とりあえず今度から一括削除したい時はALTER TABLE DROP PARTITION
クエリでカーディナリティが低いパーティションキーを指定する方法を使いたいと思います。
参考
- [AWS Glue]データカタログのパーティションをAWS CLIで更新してみた | Developers.IO
- BatchDeletePartition - AWS Glue
- AWS CLI を使用した短縮構文の使用 - AWS Command Line Interface
- Makefile 動的な変数の使い分け - SIerだけど技術やりたいブログ
- /bashでjqを使ってJSONの配列をループさせる - Qiita
- コマンドライン上でのbashを1行で (for文/if文) - Qiita
- AWS CLI での文字列への引用符の使用 - AWS Command Line Interface
以上